﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;

namespace BOW
{
    public class Common
    {
        List<string> listWordofBug = new List<string>(); // danh sách toàn bộ bug

        List<string> listValueCell = new List<string>(); // mỗi phần tử của mảng chứa 1 bug report
        private static readonly char[] delimiters = { ' ', '.', ',', ';', '\'', '_', '-', ':', '!', '?', '(', ')', '<', '>', '=', '*', '/', '[', ']', '{', '}', '\\', '"', '\r', '\n' };
        ConnectDB connect = new ConnectDB();
        Const con = new Const();
        public List<string> processWordofBug(string Arraytext)
        {
            List<string> listText = new List<string>();// danh sách chứa word_stop
            listText = GetWordLimited();// gọi file chưa word_stop.
            List<string> listTemp = new List<string>();

            // Đọc chuỗi và đưa vào mảng
            if (!string.IsNullOrEmpty(Arraytext))
            {
                while (Arraytext != string.Empty)
                {
                    listTemp.AddRange(Arraytext.Split(delimiters));
                    Arraytext = "";
                }
            }

            // Xử lí word-stop
            for (int i = 0; i < listTemp.Count; i++)
            {
                string a = listTemp[i].ToLower();
                if (listText.Contains(a))
                {
                    listTemp.Remove(listTemp[i]);
                    i--;
                }

            }
            return listTemp;
        }

        public List<string> GetWordLimited()
        {
            List<string> listText = new List<string>();// danh sách chứa word_stop
            string pathReadlimit = Environment.CurrentDirectory + "\\FileDelimited\\charlimited.txt";

            string line = "";
            // lay ra mang ki tu
            System.IO.StreamReader file = new System.IO.StreamReader(pathReadlimit);
            while ((line = file.ReadLine()) != null)
            {
                listText.AddRange(line.Split('\n'));
            }

            return listText;
        }

        public string RemoveDuplicateWords(string text)
        {
            var words = new HashSet<string>();
            text = Regex.Replace(text, "\\w+", m =>
                                 words.Add(m.Value.ToUpperInvariant())
                                     ? m.Value
                                     : String.Empty);
            return text;
        }

        // Đọc bag of word
        public Dictionary<string, double> ReadBagOfWord()
        {
            Dictionary<string, double> BOW = new Dictionary<string, double>();
            string pathBagOfWord = Environment.CurrentDirectory + "\\DataTest\\BagOfWords.txt";
            string line = null;
            // lay ra mang ki tu
            System.IO.StreamReader file = new System.IO.StreamReader(pathBagOfWord);

            while ((line = file.ReadLine()) != null)
            {
                List<string> bot = new List<string>();
                bot.AddRange(line.Split(':'));
                //bot.AddRange(line.Split(':'));
                BOW.Add(bot[0], double.Parse(bot[1].ToString()));
            }
            file.Close();
            return BOW;
        }
        // when create new bag
        public void WriteBagOfWord(Dictionary<string, double> words)
        {
            if (words.Count > 0)
            {
                string pathWriteText = Environment.CurrentDirectory + "\\DataTest\\BagOfWords.txt";
                write(words, pathWriteText);
            }

        }
        //when update bag 
        public void WriteBagOfWordUpdate(Dictionary<string, double> words)
        {
            if (words.Count > 0)
            {
                string pathWriteText = Environment.CurrentDirectory + "\\DataTest\\BagOfWords.txt";
                writeUpdate(words, pathWriteText);
            }

        }

        public Dictionary<string, int> ReadText()
        {
            Dictionary<string, int> BOW = new Dictionary<string, int>();
            try
            {
                // Dictionary<string, int> BOW = new Dictionary<string, int>();
                string pathBagOfWord = Environment.CurrentDirectory + "\\DataTest\\WriteText.txt";
                string line = "";
                // lay ra mang ki tu
                System.IO.StreamReader file = new System.IO.StreamReader(pathBagOfWord);

                while ((line = file.ReadLine()) != null)
                {
                    List<string> bot = new List<string>();
                    bot.AddRange(line.Split(':'));
                    //bot.AddRange(line.Split(':'));
                    BOW.Add(bot[0], int.Parse(bot[1].ToString()));
                }
                file.Close();

            }
            catch { }
            return BOW;
        }
        /// <summary>
        /// When create new
        /// </summary>
        /// <param name="words"></param>
        public void WriteText(Dictionary<string, double> words)
        {
            if (words.Count > 0)
            {
                string pathWriteText = Environment.CurrentDirectory + "\\DataTest\\WriteText.txt";
                write(words, pathWriteText);
            }

        }
        // when update words
        public void WriteTextUpdate(Dictionary<string, double> words)
        {
            if (words.Count > 0)
            {
                string pathWriteText = Environment.CurrentDirectory + "\\DataTest\\WriteText.txt";
                writeUpdate(words, pathWriteText);
            }

        }
        private void writeUpdate(Dictionary<string, double> words, string path)
        {
            System.IO.TextWriter tw = new System.IO.StreamWriter(path, true);
            string temp = "";
            foreach (string item in words.Keys)
            {
                if (temp != "")
                {
                    temp += "\n";
                    //temp += "\n";
                }
                temp += item + ":" + words[item].ToString();
            }
            tw.WriteLine(temp);
            tw.Close();

        }
        private void write(Dictionary<string, double> words, string path)
        {
            System.IO.TextWriter tw = new System.IO.StreamWriter(path);
            string temp = "";
            foreach (string item in words.Keys)
            {
                if (temp != "")
                {
                    temp += "\n";
                    //temp += "\n";
                }
                temp += item + ":" + words[item].ToString();
            }
            tw.WriteLine(temp);
            tw.Close();

        }
        public double d_avg; // To other page get d_avg
        public Dictionary<string, double> bag(DataTable dt, Dictionary<string, double> words, string path)
        {
            Calculator cal = new Calculator();
            List<int> getColumns = new List<int>();
            getColumns = this.disField(path);
            Dictionary<string, double> temp = new Dictionary<string, double>();
            //DataTable test = connect.getDataFromXLS(con.path);
            List<string> valuecell = new List<string>();
            string arraytext = null;
            if (dt != null)
            {
                update_Frequency(dt, words, path);
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    for (int j = 0; j < dt.Columns.Count; j++)
                    {
                        if (getColumns.Contains(j))
                            continue;
                        valuecell.Add(dt.Rows[i][j].ToString());
                        arraytext += dt.Rows[i][j].ToString() + " ";
                    }
                }
                // get d_avg
                int nndavg = 0;
                foreach (string item in valuecell)
                {
                    int ndavg = 0;
                    string sTemp = "";
                    List<string> ssTemp = new List<string>();
                    sTemp = RemoveDuplicateWords(item);
                    ssTemp = processWordofBug(sTemp);
                    foreach (string word in ssTemp)
                    {
                        if (words.ContainsKey(word))
                            ndavg++;
                    }
                    nndavg += ndavg;
                }

                //for (int i = 0; i < dt.Rows.Count; i++)
                //{
                //    valuecell.Add(dt.Rows[i][11].ToString());
                //    arraytext += dt.Rows[i][11].ToString();
                //}
                List<string> term = processWordofBug(arraytext);
                int max_f = 0;
                int N = dt.Rows.Count;
                double BR_length = words.Count;
                d_avg = nndavg / N;
                foreach (string item in words.Keys)
                {
                    if (max_f < int.Parse(words[item].ToString()))
                        max_f = int.Parse(words[item].ToString());
                }

                foreach (string item in words.Keys)
                {
                    //tinh tan suat xuat hien cua tu ti trong toan bug report
                    int df_ti = 0; // số bug report có chứa từ item trong toàn bộ bug đã có              
                    foreach (string s in valuecell)
                    {
                        if (s.ToUpper().IndexOf(item.ToUpper()) != -1) //có từ item trong câu s
                            df_ti++;
                    }
                    int f_ti = int.Parse(words[item].ToString());//số lần xuất hiện của từ item trong toàn bộ bug report
                    double idf_ti = cal.calculation_idf_ti(N, double.Parse(df_ti.ToString())); //tính idf (ti)
                    double tf_ti = cal.calculation_tf_ti_BRj(double.Parse(f_ti.ToString()), double.Parse(max_f.ToString())); // tính  tf (ti,BR)
                    double wi = cal.calculation_wi(idf_ti, tf_ti, BR_length, d_avg); // tính wi dựa vào công thức 4             

                    temp.Add(item, wi);
                }
            }
            return temp;
        }

        public Dictionary<string, int> update_Frequency(DataTable dt, Dictionary<string, double> words, string path)
        {
            Calculator cal = new Calculator();
            Dictionary<string, int> uf = new Dictionary<string, int>();
            List<string> valuecell = new List<string>();
            List<int> getColumns = new List<int>();
            getColumns = this.disField(path);
            string arraytext = null;
            if (dt != null)
            {
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    for (int j = 0; j < dt.Columns.Count; j++)
                    {
                        if (getColumns.Contains(j))
                            continue;
                        valuecell.Add(dt.Rows[i][j].ToString());
                        arraytext += dt.Rows[i][j].ToString() + " ";
                    }
                }
            }
            List<string> temp = processWordofBug(arraytext);
            Dictionary<string, int> df = cal.GetTf_qi(temp);
           
            foreach (string item in words.Keys)
            {
                foreach (string s in df.Keys)
                {
                    if (s == item)
                    {
                        uf.Add(item, int.Parse(df[s].ToString()));
                    }
                }

            }
            return uf;
        }

        public bool checkFileSize()
        {
            ConnectDB connect = new ConnectDB();
            DataTable test = connect.getDataFromXLS(@"D:\ bug-report\Source\BOW\BOW\DataTest\temp.xlsx");
            int a = test.Rows.Count;
            if (test.Rows.Count > 20)
            {
                return false;
            }
            return true;
        }

        public List<int> disField(string path)
        {
            int k = 0;
            List<int> getColumns = new List<int>();// get columns empty and litle value
            DataTable getExcel = connect.getDataFromXLS(path);
            if (getExcel != null)
            {
                while (k < getExcel.Columns.Count)
                {
                    int i = 0;
                    int j = 0;
                    foreach (DataRow r in getExcel.Rows)
                    {
                        j++;
                        List<string> lsTemp = new List<string>();
                        lsTemp.AddRange(r[k].ToString().Split(' '));
                        if (lsTemp.Count < 3)
                            i++;
                        if (i >= 10)
                        {
                            getColumns.Add(k);
                            break;
                        }
                        if (j > 20)
                            break;
                    }

                    k++;
                }
            }
            return getColumns;
        }
    }
}
